/*******************************************************
 *Copyright (c) 2017 All Rights Reserved.
 *JDK版本： 1.8
 *公司名称：
 *命名空间：com.caltco.cargo.ops.service.impl
 *文件名：  SysUserServiceImpl 
 *版本号：  V1.0.0.0
 *创建人：  daixirui
 *电子邮箱：daixirui@live.com
 *创建时间：2019-06-11 14:04
 *描述：
 *
 *=====================================================
 *修改标记
 *修改时间：2019-06-11 14:04
 *修改人：  daixirui
 *版本号：  V1.0.0.0
 *描述：
 *
 /******************************************************/
package com.caltco.cargo.ops.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.caltco.cargo.ops.auth.bo.AdminUserDetails;
import com.caltco.cargo.ops.auth.entity.UserEntity;
import com.caltco.cargo.ops.auth.utils.JwtTokenUtil;
import com.caltco.cargo.ops.common.base.gen.BaseServiceImpl;
import com.caltco.cargo.ops.common.exception.RRException;
import com.caltco.cargo.ops.common.interceptor.ShiroUtils;
import com.caltco.cargo.ops.common.utils.*;
import com.caltco.cargo.ops.modules.sys.dao.SysUserDao;
import com.caltco.cargo.ops.modules.sys.dao.UserLevelDao;
import com.caltco.cargo.ops.modules.sys.entity.SysUserEntity;
import com.caltco.cargo.ops.modules.sys.entity.UserLevel;
import com.caltco.cargo.ops.modules.sys.request.LoginRequest;
import com.caltco.cargo.ops.modules.sys.request.RegisterRequest;
import com.caltco.cargo.ops.modules.sys.request.UpdateRequest;
import com.caltco.cargo.ops.modules.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    private static String defaultPassword = "123456";
    @Autowired(required = false)
    private SimpleMessageListenerContainer simpleMessageListenerContainer;
    @Value("${login.key}")
    private String key;
    @Value("${wx.appid}")
    private String appid;
    @Autowired(required = false)
    private RabbitMQUtil rabbitMQUtil;
    @Autowired
    private RedisCacheUtil redisCacheUtil;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private DingTalkUtil dingTalkUtil;
    @Autowired
    private SysUserDao sysUserDao;
    @Value("${agilefast.redis.open}")
    private String isOpenRedis;
    @Autowired
    private StringRedisTemplate redisTemplate;
    private final UserLevelDao userLevelDao;

    public SysUserServiceImpl(UserLevelDao userLevelDao) {
        this.userLevelDao = userLevelDao;
    }


    public Long getUserIdByToken() {
        return ((AdminUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUserEntity().getUserId();
    }

    @Override
    public Boolean logout(String username, Long userId) {
//        return true;
        try {
            if (isOpenRedis.equals("true")) {
                List<String> delKeys = new ArrayList<>();
                String loginKey = redisCacheUtil.getLoginKey(username);
                delKeys.add(loginKey);
                redisCacheUtil.del(delKeys);
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public Boolean saveUser(RegisterRequest registerRequest) {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        if (registerRequest.getEmailCode() != null){
            String storedCode = ops.get(registerRequest.getEmail());
            SysUserEntity tem = sysUserDao.selectOne(new LambdaQueryWrapper<SysUserEntity>()
                    .eq(SysUserEntity::getEmail, registerRequest.getEmail()));
            if (tem != null){
                throw new RRException("该邮箱已注册账号");
            }
            if (storedCode == null || !storedCode.equals(registerRequest.getEmailCode())) {
                redisTemplate.delete(registerRequest.getEmail());
                throw new RRException("验证码错误或者已失效");
            }else {
                redisTemplate.delete(registerRequest.getEmail());
            }
        }

//        saveVerify(registerRequest);
        SysUserEntity user = new SysUserEntity();
        BeanUtils.copyProperties(registerRequest, user);
        user.setPassword(ShiroUtils.sha256(user.getPassword(), key));
        this.save(user);
        UserLevel userLevel = new UserLevel();
        userLevel.setPoint(0);
        userLevel.setLevelExp(0);
        userLevel.setHp(6);
        userLevel.setUserId(user.getId());
        userLevelDao.insert(userLevel);
        return true;
    }

    public void saveVerify(RegisterRequest registerRequest) {
        String confirmPassword = registerRequest.getConfirmPassword();
        String password = registerRequest.getPassword();
        if (!confirmPassword.equals(password)) {
            throw new RRException("两次输入的密码不一样");
        }
        String account = registerRequest.getAccount();
        // 查找用户的账号
        SysUserEntity sysUserEntity = sysUserDao.selectOne(new QueryWrapper<SysUserEntity>()
                .eq("account", account));

        if (sysUserEntity != null) {
            throw new RRException("已存在对应账号");
        }

    }

    @Override
    public Map<String, Object> verifyLogin(LoginRequest request) {

        String email = request.getEmail();
        // 查找用户的账号
        SysUserEntity sysUserEntity = sysUserDao.selectOne(new LambdaQueryWrapper<SysUserEntity>()
                .eq(SysUserEntity::getEmail, email));

        if (sysUserEntity == null) {
            throw new RRException("没找到对应账号");
        }

        if (!ShiroUtils.sha256(request.getPassword(), key).equals(sysUserEntity.getPassword())) {
            throw new RRException("密码或账号错误");
        }

        redisCacheUtil.del(Arrays.asList("Sys::Login::" + sysUserEntity.getId()));
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(sysUserEntity, userEntity);
        UserDetails userDetails = new AdminUserDetails(userEntity);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(sysUserEntity, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);


        Map<String, Object> map = new HashMap<>(2);

        // 构造JWT用户信息
        Map<String, Object> userMap = new MapUtils();
        userMap.put("username", sysUserEntity.getUsername());
        userMap.put("userId", sysUserEntity.getId());
        // 查看用户详情
        String token = jwtTokenUtil.generateTokenMap(userMap);

        map.put("userId", sysUserEntity.getId());
        map.put("email", sysUserEntity.getEmail());
        map.put("username", sysUserEntity.getUsername());
        map.put("userPhoto", sysUserEntity.getUserPhoto());
        map.put("token", token);

        return map;
    }

    @Override
    @Transactional
    public SysUserEntity updateUser(UpdateRequest updateRequest) {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        if (updateRequest.getEmailCode() != null){
            String storedCode = ops.get(updateRequest.getEmail());
            SysUserEntity tem = sysUserDao.selectOne(new LambdaQueryWrapper<SysUserEntity>()
                    .eq(SysUserEntity::getEmail, updateRequest.getEmail()));
            if (tem != null && !tem.getId().equals(getUserIdByToken())){
                throw new RRException("该邮箱已存在");
            }
            if (storedCode != null && !storedCode.equals(updateRequest.getEmailCode())) {
                redisTemplate.delete(updateRequest.getEmail());
                throw new RRException("验证码错误或者已失效");
            }else {
                redisTemplate.delete(updateRequest.getEmail());
            }
        }

        if (updateRequest.getPassword() != null && !updateRequest.getConfirmPassword().equals(updateRequest.getPassword())) {
            throw new RRException("密码和确认密码不一致");
        }
        Long id = getUserIdByToken();
        if (id == null) {
            throw new RRException("id为空");
        }
        SysUserEntity user = new SysUserEntity();
        BeanUtils.copyProperties(updateRequest, user);
        user.setId(id);
        if (StringUtils.isNotEmpty(user.getPassword())) {
            user.setPassword(ShiroUtils.sha256(user.getPassword(), key));
        }else {
            user.setPassword(null);
        }
        this.update(user);
        return this.getById(id);
    }

    @Override
    public SysUserEntity getUserInfo() {
        Long id = getUserIdByToken();
        if (id == null) {
            throw new RRException("id为空");
        }
        return this.getById(id);
    }

    @Override
    public UserDetails loadUserByUsername(String account) {
        //获取用户信息
        SysUserEntity admin = sysUserDao.selectOne(new QueryWrapper<SysUserEntity>()
                .eq("account", account));
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(admin, userEntity);
        if (admin != null) {
            return new AdminUserDetails(userEntity);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }
}
